#ifndef SIMPLE_SUPPORT_ALGORITHM_MISMATCH_HPP
#define SIMPLE_SUPPORT_ALGORITHM_MISMATCH_HPP

#include <utility> // std::pair std::move
#include <type_traits> // std::enable_if_t
#include <iterator> // std::begin std::end
#include "traits.hpp" // is_iterable_v is_range_v

namespace simple::support
{

	// cause can't even count on libstdc++ devs to implement a mismatch without
	// copying the iterator bajillion times... simple rule - pass by const ref,
	// is it that hard? your own compiler can't short circuit a simple and/or
	// functors if they accept value instead of const ref, and you are here
	// copying user defined types willy nilly, for no good reason... "but
	// standard requires, bhaahaa"... standard does not require you to be a
	// dick, ffs...
	// i don't care how regular you wish the world to be, input iterators are move only, deal with it
	template <typename It, typename It2,
		std::enable_if_t<is_iterable_v<It> && is_iterable_v<It2>>* = nullptr>
	[[nodiscard]] constexpr
	std::pair<It,It2> mismatch(It begin, const It& end, It2 begin2)
	// TODO: noexcept(...)
	{
		while(begin != end && *begin == *begin2)
			++begin, ++begin2;
		return {std::move(begin),std::move(begin2)};
	}

	template <typename It, typename It2,
		std::enable_if_t<is_iterable_v<It> && is_iterable_v<It2>>* = nullptr>
	[[nodiscard]] constexpr
	std::pair<It,It2> mismatch(It begin, const It& end, It2 begin2, const It2& end2)
	// TODO: noexcept(...)
	{
		while(begin != end && begin2 != end2 && *begin == *begin2)
			++begin, ++begin2;
		return {std::move(begin),std::move(begin2)};
	}

	template <typename Range, typename Range2,
		std::enable_if_t<is_range_v<Range> && is_range_v<Range2>>* = nullptr>
	[[nodiscard]] constexpr
	auto mismatch(Range&& r, Range2&& r2)
	// TODO: noexcept(...)
	{
		using std::begin; using std::end;
		return support::mismatch(begin(r), end(r), begin(r2), end(r2));
	}

} // namespace simple::support

#endif /* end of include guard */
